#ifndef BONES_BIPED_ANIMS_H_
#define BONES_BIPED_ANIMS_H_

#include "num/named_set.h"
#include "math/vec2.h"
#include <vector>

namespace bones  
{

struct				BipedAnimFrame
{
	math::Vec2		Pos;
	float			Rot;
	int				Flags;
	
	enum			FLAGS
	{
		FLAG_VISIBLE = 0x01 << 0
	};
	void			SetFlag(FLAGS f) { Flags |= f; };
	bool			TestFlag(FLAGS f) { return (Flags & f) > 0; };
};

struct				BipedBone
{
	static const char			NAME_LENGTH = 64;
	unsigned int				ID;
	char						Name[NAME_LENGTH];
	float						Length;
	char						DefaultImg[NAME_LENGTH];
	float						DefaultSortL;
	float						DefaultSortR;
	BipedAnimFrame*				FrameA;
	int							FrameC;
	char						GameData[NAME_LENGTH];

	void						GetBlendedFrame(float Frame, math::Vec2& Pos, float& Rot, bool Wrap);
	void						GetFrame(int Frame, math::Vec2& Pos, float& Rot, bool Wrap);
	void						GetFrameVec(int Frame, math::Vec2& Pos, math::Vec2& Dir, bool Wrap);
	void						GetFrameAngle(int Frame, math::Vec2& Pos, float& Angle, bool Wrap);

	void						GetBlendedFrameVec(float Frame, math::Vec2& Pos, math::Vec2& Dir, bool Wrap);
	BipedAnimFrame*				GetRawFrame(int Frame, bool Wrap);

	static	void SetString(char* Out, const std::string& In)		// simple utility
	{
		if (In.size() < NAME_LENGTH)
		{
			strcpy(Out, In.c_str());	// simple
		} else
		{
			memcpy(Out, &In[In.size()-(NAME_LENGTH+1)], NAME_LENGTH-1);
			Out[NAME_LENGTH-1] = '\0';
		}
	}
};

struct				BipedAnimation
{
	char						Name[BipedBone::NAME_LENGTH];
	char						BasePath[BipedBone::NAME_LENGTH];
	BipedBone*					BoneA;
	int							BoneC;
	float						RunTime;
	int							Frames;
	math::Vec2					Min, Max;
	
	BipedBone*					GetBone(const std::string& Name)
	{
		return GetBone(num::CRC32::FastHash(Name));
	}

	BipedBone*					GetBone(unsigned int ID)
	{
		for (int i=0; i<BoneC; i++)
		{
			if (BoneA[i].ID == ID) return &BoneA[i];
		}
		return NULL;
	};	//! fetch and cache, the reset cache when changing animation
	int							GetFrame(float t);
};

class		BipedAnimationSet
{
public:
								BipedAnimationSet();
								~BipedAnimationSet();
	static BipedAnimationSet&	Instance();
	void						RefreshAll();
	void						AddAll();
	void						AddAnimationLua(const std::string& Name);
	void						AddAnimationBin(const std::string& Name);
	BipedAnimation*				GetAnimation(const std::string& Name);
	float						GetAnimationTime(const std::string& Name, float Default = 1.0f);
	void						SaveAnimationBin(BipedAnimation*	pAnim);
	void						SaveAll();
	void						ConvertAll();
	num::NamedSet<BipedAnimation*>&		GetAnimations() { return m_Animations; };
private:
	num::NamedSet<BipedAnimation*>		m_Animations;
};

} // namespace bones  

#endif // SON_BIPED_ANIMS_H_